package org.sshbot;

import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.View;
import de.mud.terminal.VT320;
import org.sshbot.transport.Transport;

import static org.sshbot.util.LogHelper.DEBUG;

public class TerminalKeyListener implements View.OnKeyListener {

	private final Transport transport;
	private TerminalView terminalView;
	private VT320 buffer;
	public KeyCharacterMap keymap = KeyCharacterMap.load(KeyCharacterMap.BUILT_IN_KEYBOARD);
	private boolean ctrlPressed = false;
	  
	public final static int KEY_PAGE_UP = 92;  
	public final static int KEY_PAGE_DOWN = 93;
	public final static int KEY_CTRL = 4096;

	public TerminalKeyListener(TerminalView terminalView, Transport transport, VT320 buffer) {
		this.terminalView = terminalView;
		this.transport = transport;
		this.buffer = buffer;
	}

	public boolean onKey(View v, int keyCode, KeyEvent event) {
		int key = terminalView.keymap.get(keyCode, event.getMetaState());

		DEBUG("Got key data:", keyCode, event.getCharacters(), key);

		if (event.getCharacters() != null) {
			transport.write(event.getCharacters().getBytes());
			
			return true;
		}
		
		if (event.getAction() != KeyEvent.ACTION_DOWN) return false;
		
		// check for terminal resizing keys
        // TODO: see if there is a way to make sure we dont "blip"
        if(keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
        		terminalView.increaseFontSize();
                return true;
        } else if(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
        		terminalView.decreaseFontSize();
                return true;
        }
        
		boolean printing = (keymap.isPrintingKey(keyCode) || keyCode == KeyEvent.KEYCODE_SPACE);
		 // otherwise pass through to existing session
        // print normal keys
        if (printing) {
                //int key = keymap.get(keyCode, event.getMetaState());
                if (ctrlPressed) {
	                // Support CTRL-A through CTRL-Z
	                key =  keyAsControl(key);
	                
	                ctrlPressed = false;
                }
                //this.stdin.write(key);
                transport.write(key);
                return true;
        }

        // look for special chars
        
		switch (keyCode) {
			case KeyEvent.KEYCODE_DPAD_LEFT:
				buffer.keyPressed(VT320.KEY_LEFT, ' ', 0);
				return true;
			
			case KeyEvent.KEYCODE_DPAD_RIGHT:
				buffer.keyPressed(VT320.KEY_RIGHT, ' ', 0);
				return true;

			case KeyEvent.KEYCODE_DPAD_UP:
				buffer.keyPressed(VT320.KEY_UP, ' ', 0);
				return true;
			
			case KeyEvent.KEYCODE_DPAD_DOWN:
				buffer.keyPressed(VT320.KEY_DOWN, ' ', 0);
				return true;	
				
			case KeyEvent.KEYCODE_ENTER:
//				buffer.keyPressed(VT320.KEY_ENTER, ' ', 0);
				buffer.keyTyped(VT320.KEY_ENTER, ' ', 0);
				return true;
			
			case KeyEvent.KEYCODE_DEL:
				buffer.keyPressed(VT320.KEY_BACK_SPACE, ' ', 0);
				return true;
				
			case KeyEvent.KEYCODE_SEARCH:
				//buffer.keyTyped(VT320.KEY_ESCAPE, ' ', 0);
				transport.write(0x09);
				return true;
				
			case KeyEvent.META_SHIFT_ON:
				buffer.keyTyped(VT320.KEY_SHIFT, ' ', 0);
				return true;	
				
			case KEY_CTRL:
				buffer.keyTyped(VT320.KEY_CONTROL, ' ', 0);
				return true;		
				
			case KeyEvent.KEYCODE_TAB: // Support for Hard Keyboard TAB
			    transport.write(0x09);
			    return true;
			    
			case KeyEvent.KEYCODE_UNKNOWN: 
			    transport.write(0x1B);	// Esc
			    return true;    
			    
			case KEY_PAGE_UP:
				buffer.keyPressed(VT320.KEY_PAGE_UP, ' ', 0);
				return true;    
				
			case KEY_PAGE_DOWN:
				buffer.keyPressed(VT320.KEY_PAGE_DOWN, ' ', 0);
				return true;    			
							
			case KeyEvent.KEYCODE_DPAD_CENTER:	
				 // TODO: Add some visual indication of Ctrl state
                if (ctrlPressed) {
                        //stdin.write(0x1B); // ESC
                		transport.write(0x1B);	// Esc
                        ctrlPressed = false;
                } else
                        ctrlPressed = true;
                return true;	
		}

		transport.write(new String(Character.toChars(key)).getBytes());

		return false;
	}
	
	 public int keyAsControl(int key) {
         // Support CTRL-a through CTRL-z
         if (key >= 0x61 && key <= 0x7A)
                 key -= 0x60;
         // Support CTRL-A through CTRL-_
         else if (key >= 0x41 && key <= 0x5F)
                 key -= 0x40;
         // CTRL-space sends NULL
         else if (key == 0x20)
                 key = 0x00;
         // CTRL-? sends DEL
         else if (key == 0x3F)
                 key = 0x7F;
         else if (key >= 0x40 && key <= 0x59)
             key -= 0x39;
         return key;
 }

	
}
